package com.yujiahao.bigdata.rdd.Serializable

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
    TODO 一般的我们希望将操作的步骤封装成一个对象来使用，下面是对封装的说明
      1、类的构造参数，主要用于将类的外部数据传递给类的内部
      2、Scala 中的构造参数的使用相对来说有点复杂，默认情况下，构造参数只是类的局部变量
      3、但是特殊场合下，可以将构造参数作为类的属性存在。
        1）将构造参数作为类的属性使用，声明时增加val、var前缀。
        2）如果构造参数在其他方法中使用，那么必须将参数设定为类的属性，但是是私有的
 */
object Spark01_Serializble {
  def main(args: Array[String]): Unit = {
    //TODO 1、获得Spark环境的连接
    // 参数解读：setAppName("当前执行程序的名字").setMaster("当前的环境")
    // 分布式环境的基本架构为 主 - 从
    val conf = new SparkConf().setAppName("WordCount").setMaster("local")
    val sc: SparkContext = new SparkContext(conf)

    //TODO 3、业务逻辑

    val rdd: RDD[String] = sc.makeRDD(List("Hello", "hive", "hbase", "Hadoop"))
    //TODO 一般的我们可以使用下面两行代码进行处理，但是我希望将操作进行封装
    //rdd.filter(_.startsWith("H")).collect().foreach(println)

    //3.1 创建一个对象
    val search: Search = new Search("H")
    //3.2 调用方法
    search.matchData(rdd)
    //TODO 2、关闭Spark环境的连接
    sc.stop()

  }

  //TODO 类的声明有三种方法，方法一：这个类要继承序列化
  // class Search(query: String) extends Serializable {
  //TODO 方法二：直接使用样例类，也可运行成功
  //case class Search(query: String) {
  //  TODO 方法三，将构造参数作为类的属性使用，声明时增加val、var前缀。
  // class Search(val query: String) extends Serializable{
  //TODO 方法四，将类的构造器的参数当做属性来用，可以不用序列化，因为字符串本身是支持序列化的俄，但是这个属性必须是私有的
  class Search(query: String) {
    def matchData(rdd: RDD[String]): Unit = {
      //TODO 方法四
      val q = this.query
      rdd.filter(_.startsWith(q)).collect().foreach(println)

      //  TODO 方法一、二、三
      // rdd.filter(_.startsWith(this.query)).collect().foreach(println)
    }
  }

}
